using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Data;
using System.Configuration;
using com.paypal.sdk.services;
using com.paypal.sdk.profiles;
using com.paypal.sdk.util;
using NENAData.LINQ;
using NENAData.NENAProvinces;

/// <summary>
/// Summary description for NVPAPICaller
/// </summary>
public class NVPAPICaller
{
    //PayPal Web Reference
    //https://www.paypal.com/wsdl/PayPalSvc.wsdl

    private static TraceSource _source = new TraceSource("PayPal");
    private string pendpointurl;

    //Flag that determines the PayPal environment (live or sandbox)
    public bool bSandbox;

    private readonly string cancelURL = ConfigurationManager.AppSettings["CancelURL"];
    private readonly string strCurrencyCode = ConfigurationManager.AppSettings["CurrencyCode"];
    private readonly string strPaymentAction = ConfigurationManager.AppSettings["PaymentAction"];

    //HttpWebRequest Timeout specified in milliseconds 
    private const int Timeout = 5000;

    //WSDL
    //https://www.paypal.com/wsdl/PayPalSvc.wsdl 
    //https://www.paypal.com/wsdl/eBLBaseComponents.xsd
    //https://www.paypal.com/wsdl/CoreComponentTypes.xsd

    //https://cms.paypal.com/cms_content/en_US/files/developer/soap_GetTransactionDetails_cs.txt
    //https://cms.paypal.com/cms_content/en_US/files/developer/nvp_ECSetExpressCheckout_PayLater_cs.txt

    //Customizing Express Checkout
    //https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ECCustomizing

    /// <summary>
    /// https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_SetExpressCheckout
    /// </summary>
    /// <param name="amount"></param>
    /// <param name="Description"></param>
    /// <param name="intAffiliate"></param>
    /// <param name="strReturnURL"></param>
    /// <returns></returns>
    public NVPCodec ECSetExpressCheckout_PayLaterCode(string amount, string Description, int intAffiliate, string strReturnURL)
    {
        
        NENAAffiliate oAPI = new NENAAffiliate(); 
        NVPCallerServices NVPcaller = new NVPCallerServices();
        IAPIProfile APIprofile = ProfileFactory.createSignatureAPIProfile();

       Affiliate oAffiliate = oAPI.GetAffiliate_byAffiliateID(intAffiliate);
       APIprofile.APIUsername = oAffiliate.PayPalAPIUserName;
       APIprofile.APIPassword = oAffiliate.PayPalAPIPassword;
       APIprofile.APISignature = oAffiliate.PayPalAPISignature;
       APIprofile.Environment = SetEnvironment(intAffiliate);
       NVPcaller.APIProfile = APIprofile;

       NVPCodec encoder = new NVPCodec();
       encoder["VERSION"] = "72.0";
       encoder["METHOD"] = "SetExpressCheckout";
       encoder["RETURNURL"] = strReturnURL;
       encoder["CANCELURL"] = cancelURL;

        //payment details section
       encoder["PAYMENTREQUEST_0_DESC"] = Description;
       encoder["PAYMENTREQUEST_0_PAYMENTACTION"] = strPaymentAction;
       encoder["PAYMENTREQUEST_0_CURRENCYCODE"] = strCurrencyCode;
       encoder["PAYMENTREQUEST_0_AMT"] = amount;
       encoder["PAYMENTREQUEST_0_ITEMAMT"] = amount;

        //payment details
       encoder["PAYMENTREQUEST_0_ITEMAMT0"] = amount;
       encoder["PAYMENTREQUEST_0_AMT0"] = amount;
       encoder["PAYMENTREQUEST_0_QTY0"] = "1";
       encoder["PAYMENTREQUEST_0_DESC0"] = Description;

       //payment details ITEM section
       encoder["L_PAYMENTREQUEST_0_AMT0"] = amount;
       encoder["L_PAYMENTREQUEST_0_QTY0"] = "1";
       encoder["L_PAYMENTREQUEST_0_NAME0"] = Description;

       if (intAffiliate == 99)
       {
           encoder["HDRIMG"] = "http://images.nena.ca/Zumba/Loca.Fitness_300dpi_302x122.jpg";
           encoder["HDRBACKCOLOR"] = "8AA3B0";
           encoder["HDRBORDERCOLOR"] = "8AA3B0";
       }
       else
       {
           encoder["HDRIMG"] = "http://images.nena.ca/nena/NENAlogo_2011.png";
           encoder["HDRBACKCOLOR"] = "8AA3B0";
           encoder["HDRBORDERCOLOR"] = "8AA3B0";
       }
       string pStrrequestforNvp = encoder.Encode();
       string pStresponsenvp = NVPcaller.Call(pStrrequestforNvp);

       NVPCodec NVPCodec_decoder = new NVPCodec();
       NVPCodec_decoder.Decode(pStresponsenvp);
       return NVPCodec_decoder;

    }

    /// <summary>
    /// ConfirmPayment: The method that calls SetExpressCheckout API, invoked from the 
    /// Billing Page EC placement
    /// https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_DoExpressCheckoutPayment
    /// </summary>
    /// <param name="token"></param>
    /// <param ref name="retMsg"></param>
    /// <returns></returns>
    public bool ConfirmPayment(string finalPaymentAmount, string Description, string token, string PayerId, ref NVPCodec decoder, ref string retMsg, int intAffiliate)
    {

        NVPCodec encoder = new NVPCodec();
        encoder["METHOD"] = "DoExpressCheckoutPayment";
        encoder["TOKEN"] = token;
        encoder["PAYERID"] = PayerId;

        //payment details section
        encoder["PAYMENTREQUEST_0_CURRENCYCODE"] = strCurrencyCode;
        encoder["PAYMENTREQUEST_0_PAYMENTACTION"] = strPaymentAction;
        encoder["PAYMENTREQUEST_0_AMT"] = finalPaymentAmount;
        encoder["PAYMENTREQUEST_0_ITEMAMT"] = finalPaymentAmount;
        encoder["PAYMENTREQUEST_0_DESC"] = Description;

        //payment details
        encoder["PAYMENTREQUEST_0_ITEMAMT0"] = finalPaymentAmount;
        encoder["PAYMENTREQUEST_0_AMT0"] = finalPaymentAmount;
        encoder["PAYMENTREQUEST_0_QTY0"] = "1";
        encoder["PAYMENTREQUEST_0_DESC0"] = Description;

        string pStrrequestforNvp = encoder.Encode();
        string pStresponsenvp = HttpCall(pStrrequestforNvp, intAffiliate);

        decoder.Decode(pStresponsenvp);

        string strAck = decoder["ACK"].ToLower();
        if (strAck != null && (strAck == "success" || strAck == "successwithwarning"))
        {
            return true;
        }
        else
        {
            retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" +
                "Desc=" + decoder["L_SHORTMESSAGE0"] + "&" +
                "Desc2=" + decoder["L_LONGMESSAGE0"];

            return false;
        }
    }
    /// <summary>
        /// ShortcutExpressCheckout: The method that calls SetExpressCheckout API
    /// https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_SetExpressCheckout
    /// </summary>
    /// <param name="amt"></param>
    /// <param name="Description"></param>
    /// <param name="token"></param>
    /// <param name="retMsg"></param>
    /// <param name="intAffiliate"></param>
    /// <param name="strReturnURL"></param>
    /// <returns></returns>
    public bool ShortcutExpressCheckout(string amt, string Description,  ref string token, ref string retMsg, int intAffiliate, string strReturnURL)
    {

        try
        {

            bSandbox = intAffiliate == 0;
            string host = SetHost();

            NVPCodec decoder = ECSetExpressCheckout_PayLaterCode(amt, Description, intAffiliate, strReturnURL);

            string strAck = decoder["ACK"].ToLower();
            if (strAck != null && (strAck == "success" || strAck == "successwithwarning"))
            {
                token = decoder["TOKEN"];

                _source.TraceEvent(TraceEventType.Information, 0, "ShortcutExpressCheckout tokenID : " + token);
                //string ECURL = "https://" + host + "/cgi-bin/webscr?cmd=_express-checkout&" + "&token=" + token;
                string ECURL = "https://" + host + "/cgi-bin/webscr?cmd=_express-checkout&token=" + token;

                retMsg = ECURL;
                return true;
            }
            else
            {
                retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" +
                    "Version=" + decoder["VERSION"] + "&" +
                    "Desc=" + decoder["L_SHORTMESSAGE0"] + "&" +
                    "Desc2=" + decoder["L_LONGMESSAGE0"];

                return false;
            }
        }
        catch(Exception ex)
        {
            string strerror;
            strerror = ex.InnerException.Message;
            throw;
        }
    }

    private string SetEnvironment(int intAffiliate)
    {

        switch (intAffiliate)
        {
            case 0:
                return "sandbox";
            default:
                return "live";
        }
    }

    private string  SetHost()
    {
        _source.TraceEvent(TraceEventType.Information, 0, "ShortcutExpressCheckout SetHost Sandbox: " + bSandbox);

        if (bSandbox)
        {
            pendpointurl = "https://api-3t.sandbox.paypal.com/nvp";
            return "www.sandbox.paypal.com";
        }
        else
        {
            pendpointurl = "https://api-3t.paypal.com/nvp";
            return "www.paypal.com";
        } 
    }
    

    
    /// <summary>
    /// HttpCall: The main method that is used for all API calls
    /// </summary>
    /// <param name="NvpRequest"></param>
    /// <param name="intAffiliate"></param>
    /// <returns></returns>
    public string HttpCall(string NvpRequest, int intAffiliate) //CallNvpServer
    {
        //needed for end point
        bSandbox = intAffiliate == 0;
        string host = SetHost();

        string result = "";

        //To Add the credentials from the profile
        NVPConnection NVPCon = new NVPConnection();
        
        string strPost = NvpRequest + "&" + NVPCon.buildCredentialsNVPString(intAffiliate);

        _source.TraceEvent(TraceEventType.Information, 0, "HttpCall pendpointurl : " + pendpointurl);
        HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(pendpointurl);
        objRequest.Timeout = Timeout;
        objRequest.Method = "POST";
        objRequest.ContentLength = strPost.Length;

        try
        {
            using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
            {
                myWriter.Write(strPost);
            }

            //Retrieve the Response returned from the NVP API call to PayPal
            HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
            using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
            {
                result = sr.ReadToEnd();
            }
        }
        catch (Exception)
        {
            /*
            if (log.IsFatalEnabled)
            {
                log.Fatal(e.Message, this);
            }*/
        }
        return result;
    }

    /// <summary>
    /// GetShippingDetails: The method that calls SetExpressCheckout API, invoked from the 
    /// Billing Page EC placement
    /// </summary>
    /// <param name="token"></param>
    /// <param ref name="retMsg"></param>
    /// <returns></returns>
    public bool GetShippingDetails(string token, ref string PayerId, ref string ShippingAddress, ref string retMsg, int intAffiliate)
    {

        string host = SetHost();

        NVPCodec encoder = new NVPCodec();
        encoder["METHOD"] = "GetExpressCheckoutDetails";
        encoder["TOKEN"] = token;

        string pStrrequestforNvp = encoder.Encode();
        string pStresponsenvp = HttpCall(pStrrequestforNvp, intAffiliate);

        NVPCodec decoder = new NVPCodec();
        decoder.Decode(pStresponsenvp);

        string strAck = decoder["ACK"].ToLower();
        if (strAck != null && (strAck == "success" || strAck == "successwithwarning"))
        {
            ShippingAddress = "<table><tr>";
            ShippingAddress += "<td> First Name </td><td>" + decoder["FIRSTNAME"] + "</td></tr>";
            ShippingAddress += "<td> Last Name </td><td>" + decoder["LASTNAME"] + "</td></tr>";
            ShippingAddress += "<td colspan='2'> Shipping Address</td></tr>";
            ShippingAddress += "<td> Name </td><td>" + decoder["SHIPTONAME"] + "</td></tr>";
            ShippingAddress += "<td> Street1 </td><td>" + decoder["SHIPTOSTREET"] + "</td></tr>";
            ShippingAddress += "<td> Street2 </td><td>" + decoder["SHIPTOSTREET2"] + "</td></tr>";
            ShippingAddress += "<td> City </td><td>" + decoder["SHIPTOCITY"] + "</td></tr>";
            ShippingAddress += "<td> State </td><td>" + decoder["SHIPTOSTATE"] + "</td></tr>";
            ShippingAddress += "<td> Zip </td><td>" + decoder["SHIPTOZIP"] + "</td>";
            ShippingAddress += "</tr>";

            return true;
        }
        else
        {
            retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" +
                "Desc=" + decoder["L_SHORTMESSAGE0"] + "&" +
                "Desc2=" + decoder["L_LONGMESSAGE0"];

            return false;
        }
    }
    //private static bool SandBoxMode()
    //{
    //    if (ConfigurationManager.AppSettings["SandBoxMode"].ToLower() == "true")
    //    {
    //        return true;
    //    }
    //    {
    //        return false;
    //    }
    //}

    /// <summary>
    /// MarkExpressCheckout: The method that calls SetExpressCheckout API, invoked from the 
    /// Billing Page EC placement
    /// </summary>
    /// <param name="amt"></param>
    /// <param ref name="token"></param>
    /// <param ref name="retMsg"></param>
    /// <returns></returns>
    //public bool MarkExpressCheckout(string amt, 
    //                    string shipToName, string shipToStreet, string shipToStreet2,
    //                    string shipToCity, string shipToState, string shipToZip, 
    //                    string shipToCountryCode,ref string token, ref string retMsg)
    //{
    //    string host = SetHost();

    //    NVPCodec encoder = new NVPCodec();
    //    encoder["METHOD"] = "SetExpressCheckout";
    //    encoder["RETURNURL"] = returnURL;
    //    encoder["CANCELURL"] = cancelURL;
    //    encoder["AMT"] = amt;
    //    encoder["PAYMENTACTION"] = strPaymentAction;
    //    encoder["CURRENCYCODE"] = strCurrencyCode;
    //    encoder["NO_SHIPPING"] = "1";

    //    //shipping not used
    //    //Optional Shipping Address entered on the merchant site
    //    //encoder["SHIPTONAME"]       = shipToName;
    //    //encoder["SHIPTOSTREET"]     = shipToStreet;
    //    //encoder["SHIPTOSTREET2"]    = shipToStreet2;
    //    //encoder["SHIPTOCITY"]       = shipToCity;
    //    //encoder["SHIPTOSTATE"]      = shipToState;
    //    //encoder["SHIPTOZIP"]        = shipToZip;
    //    //encoder["SHIPTOCOUNTRYCODE"]= shipToCountryCode;

    //    string pstrRequestForNVP = encoder.Encode();
    //    string pstrResponseNVP = HttpCall(pstrRequestForNVP);

    //    NVPCodec decoder = new NVPCodec();
    //    decoder.Decode(pstrResponseNVP);

    //    string strAck = decoder["ACK"].ToLower();
    //    if (strAck != null && (strAck == "success" || strAck == "successwithwarning"))
    //    {
    //        token = decoder["TOKEN"];

    //        string ECURL = "https://" + host + "/cgi-bin/webscr?cmd=_express-checkout&" + "&token=" + token;

    //        retMsg = ECURL;
    //        return true;
    //    }
    //    else
    //    {
    //        retMsg = "ErrorCode=" + decoder["L_ERRORCODE0"] + "&" +
    //            "Desc=" + decoder["L_SHORTMESSAGE0"] + "&" +
    //            "Desc2=" + decoder["L_LONGMESSAGE0"];

    //        return false;
    //    }
    //}

}